from rest_framework import viewsets, status, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser
from django_filters.rest_framework import DjangoFilterBackend
from django.http import HttpResponse
from django.utils import timezone
from .models import BillOfMaterials, BOMComponent, AlternativeMaterial, BOMDocument, BOMVersion
from .serializers import (
    BillOfMaterialsSerializer, 
    BOMCreateUpdateSerializer,
    BOMComponentSerializer,
    AlternativeMaterialSerializer,
    BOMDocumentSerializer,
    BOMVersionSerializer
)
from .dict_utils import get_dict_data_by_type
from utils.custom_model_viewSet import CustomModelViewSet
from decimal import Decimal
import io
import pandas as pd
from datetime import datetime


class BillOfMaterialsViewSet(CustomModelViewSet):
    """产品BOM视图集，支持多类型BOM管理和企业级功能"""
    queryset = BillOfMaterials.objects.filter(is_deleted=False).order_by('-create_time')
    serializer_class = BillOfMaterialsSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['product_id', 'bom_type', 'lifecycle_status', 'is_active', 'status']
    search_fields = ['product__name', 'product__sku', 'current_version', 'description']
    
    def get_serializer_class(self):
        if self.action in ['create', 'update', 'partial_update']:
            return BOMCreateUpdateSerializer
        return BillOfMaterialsSerializer
    
    def get_queryset(self):
        """增强的查询集，支持多条件过滤"""
        queryset = super().get_queryset()
        
        # 按BOM类型过滤
        bom_type = self.request.query_params.get('bom_type')
        if bom_type:
            queryset = queryset.filter(bom_type=bom_type)
        
        # 按生命周期状态过滤
        lifecycle_status = self.request.query_params.get('lifecycle_status')
        if lifecycle_status:
            queryset = queryset.filter(lifecycle_status=lifecycle_status)
        
        # 按BOM状态过滤
        status = self.request.query_params.get('status')
        if status:
            queryset = queryset.filter(status=status)
        
        # 按日期范围过滤
        start_date = self.request.query_params.get('start_date')
        end_date = self.request.query_params.get('end_date')
        if start_date and end_date:
            queryset = queryset.filter(
                effective_date__lte=end_date,
                expiry_date__gte=start_date
            )
        
        # 支持查看已删除的数据（管理员权限）
        show_deleted = self.request.query_params.get('show_deleted', 'false')
        if show_deleted.lower() == 'true' and self.request.user.has_perm('product.view_deleted_bom'):
            queryset = BillOfMaterials.objects.all().order_by('-create_time')
        
        return queryset
    
    @action(detail=False, methods=['get'])
    def check_bom_code(self, request):
        """检查BOM编码唯一性"""
        bom_code = request.query_params.get('bom_code')
        exclude_id = request.query_params.get('exclude_id')
        
        if not bom_code:
            return Response(
                {'error': 'BOM编码不能为空'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 检查BOM编码唯一性
        queryset = BillOfMaterials.objects.filter(bom_code=bom_code, is_deleted=False)
        
        # 如果是编辑模式，排除当前BOM
        if exclude_id:
            queryset = queryset.exclude(bom_id=exclude_id)
        
        is_unique = not queryset.exists()
        
        return Response({'is_unique': is_unique})
    
    def perform_destroy(self, instance):
        """实现软删除"""
        instance.is_deleted = True
        instance.save()
    
    @action(detail=True, methods=['post'])
    def restore(self, request, pk=None):
        """恢复已删除的BOM"""
        try:
            # 查找所有状态（包括已删除）的记录
            instance = BillOfMaterials.objects.get(pk=pk)
            if instance.is_deleted:
                instance.is_deleted = False
                instance.save()
                return Response({'message': 'BOM恢复成功'})
            else:
                return Response({'message': '该BOM未被删除'}, status=status.HTTP_400_BAD_REQUEST)
        except BillOfMaterials.DoesNotExist:
            return Response({'error': 'BOM不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    @action(detail=True, methods=['post'])
    def calculate_cost(self, request, pk=None):
        """计算BOM总成本"""
        try:
            bom = self.get_object()
            total_cost = Decimal('0')
            
            # 递归计算所有组件成本
            def calculate_component_cost(component):
                comp_cost = Decimal('0')
                # 计算当前组件成本
                if component.unit_cost and component.quantity:
                    comp_cost = component.unit_cost * component.quantity * component.usage_rate
                    component.total_cost = comp_cost
                    component.save()
                elif component.material.standard_cost and component.quantity:
                    component.unit_cost = component.material.standard_cost
                    comp_cost = component.unit_cost * component.quantity * component.usage_rate
                    component.total_cost = comp_cost
                    component.save()
                
                # 递归计算子组件成本
                for subcomponent in component.subcomponents.filter(is_deleted=False):
                    comp_cost += calculate_component_cost(subcomponent)
                
                return comp_cost
            
            # 遍历顶层组件计算总成本
            for component in bom.components.filter(parent_component__isnull=True, is_deleted=False):
                total_cost += calculate_component_cost(component)
            
            # 更新BOM总成本
            bom.cost = total_cost
            bom.save()
            
            return Response({
                'bom_id': bom.bom_id,
                'total_cost': float(bom.cost) if bom.cost else 0,
                'material_cost': float(bom.cost) if bom.cost else 0,  # 暂时用总成本代替物料成本
                'labor_cost': 0,  # 劳动力成本，需要后续扩展计算逻辑
                'overhead_cost': 0,  # 间接成本，需要后续扩展计算逻辑
                'message': '成本计算成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '成本计算失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def create_version(self, request, pk=None):
        """创建新版本BOM"""
        try:
            bom = self.get_object()
            new_version_number = request.data.get('version_number')
            change_reason = request.data.get('change_reason', '')
            change_content = request.data.get('change_content', '')
            
            if not new_version_number:
                return Response({
                    'message': '版本号不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查版本号是否已存在
            if BOMVersion.objects.filter(bom=bom, version_number=new_version_number).exists():
                return Response({
                    'message': '该版本号已存在'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 将当前版本设为非当前版本
            BOMVersion.objects.filter(bom=bom, is_current=True).update(is_current=False)
            
            # 创建新版本记录
            version = BOMVersion.objects.create(
                bom=bom,
                version_number=new_version_number,
                change_reason=change_reason,
                change_content=change_content,
                created_by=request.user,
                is_current=True,
                status='DRAFT'
            )
            
            # 更新BOM的当前版本
            bom.current_version = new_version_number
            bom.save()
            
            return Response({
                'version_id': version.version_id,
                'version_number': version.version_number,
                'message': '版本创建成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本创建失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['get'])
    def version_history(self, request, pk=None):
        """获取BOM版本历史"""
        try:
            bom = self.get_object()
            versions = BOMVersion.objects.filter(bom=bom).order_by('-create_time')
            serializer = BOMVersionSerializer(versions, many=True)
            return Response(serializer.data)
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '获取版本历史失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def compare_versions(self, request, pk=None):
        """比较两个版本的差异"""
        try:
            bom = self.get_object()
            version1_id = request.data.get('version1_id')
            version2_id = request.data.get('version2_id')
            
            if not version1_id or not version2_id:
                return Response({
                    'message': '版本ID不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 这里简化实现，实际应该比较两个版本的组件差异
            # 由于我们没有版本快照，这里只返回基本信息
            return Response({
                'bom_id': bom.bom_id,
                'version1_id': version1_id,
                'version2_id': version2_id,
                'message': '版本比较功能待实现',
                'comparison_available': False
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本比较失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def approve_version(self, request, pk=None):
        """审批版本"""
        try:
            bom = self.get_object()
            version_id = request.data.get('version_id')
            
            if not version_id:
                return Response({
                    'message': '版本ID不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            version = BOMVersion.objects.get(pk=version_id, bom=bom)
            version.approval_status = 'APPROVED'
            version.approved_by = request.user
            version.approved_at = timezone.now()
            version.status = 'ACTIVE'
            version.save()
            
            return Response({
                'version_id': version.version_id,
                'message': '版本审批成功'
            })
        except BOMVersion.DoesNotExist:
            return Response({
                'message': '版本不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本审批失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['post'])
    def import_bom(self, request):
        """导入BOM数据"""
        # 这里可以实现BOM数据导入的逻辑
        # 通常会涉及文件上传和解析
        return Response({
            'message': 'BOM导入接口已预留'
        }, status=status.HTTP_200_OK)
    
    @action(detail=True, methods=['get'])
    def export_bom(self, request, pk=None):
        """导出BOM数据"""
        # 这里可以实现BOM数据导出的逻辑
        # 通常会生成Excel或PDF文件
        return Response({
            'message': 'BOM导出接口已预留'
        }, status=status.HTTP_200_OK)
    
    @action(detail=False, methods=['get'])
    def download_template(self, request):
        """下载BOM导入模板"""
        try:
            # 创建Excel工作簿
            output = io.BytesIO()
            writer = pd.ExcelWriter(output, engine='openpyxl')
            
            # 创建BOM主表模板
            bom_template = pd.DataFrame({
                '产品ID': ['必填：产品的唯一标识'],
                'BOM类型': ['必填：EBOM/MBOM/SBOM'],
                '版本': ['必填：BOM版本号'],
                '生效日期': ['必填：YYYY-MM-DD'],
                '失效日期': ['选填：YYYY-MM-DD'],
                '描述': ['选填：BOM描述信息']
            })
            bom_template.to_excel(writer, sheet_name='BOM主表', index=False)
            
            # 创建BOM组件模板
            component_template = pd.DataFrame({
                '产品ID': ['必填：与BOM主表匹配的产品ID'],
                '物料ID': ['必填：组件物料的唯一标识'],
                '数量': ['必填：组件数量'],
                '单位': ['必填：数量单位'],
                '使用比例': ['必填：默认1.0'],
                '损耗率': ['必填：默认0.0'],
                '顺序号': ['必填：组件排序'],
                '工作站': ['选填：生产工作站'],
                '前置时间': ['选填：准备时间'],
                '首选供应商ID': ['选填：供应商ID'],
                '备注': ['选填：组件说明']
            })
            component_template.to_excel(writer, sheet_name='BOM组件', index=False)
            
            writer.close()
            output.seek(0)
            
            # 设置响应头
            response = HttpResponse(
                output.read(),
                content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
            response['Content-Disposition'] = 'attachment; filename="BOM导入模板.xlsx"'
            
            return response
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '模板生成失败'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['get'])
    def cost_analysis(self, request, pk=None):
        """获取BOM成本分析"""
        try:
            bom = self.get_object()
            analysis_level = request.query_params.get('analysis_level', 1)
            
            # 计算总成本汇总
            total_cost = bom.cost or Decimal('0')
            material_cost = total_cost  # 简化处理，实际应该区分不同成本类型
            labor_cost = Decimal('0')
            overhead_cost = Decimal('0')
            other_cost = Decimal('0')
            
            # 获取成本明细
            details = []
            detail_id = 1
            
            for component in bom.components.all():
                if component.level <= int(analysis_level):
                    comp_cost = component.total_cost or Decimal('0')
                    percentage = (comp_cost / total_cost * 100) if total_cost > 0 else 0
                    
                    details.append({
                        'detail_id': detail_id,
                        'material_name': component.material.name,
                        'material_code': component.material.sku,
                        'quantity': float(component.quantity),
                        'unit': component.unit,
                        'unit_cost': float(component.unit_cost or 0),
                        'total_cost': float(comp_cost),
                        'cost_percentage': float(percentage),
                        'level': component.level,
                        'component_id': component.component_id
                    })
                    detail_id += 1
            
            return Response({
                'summary': {
                    'total_cost': float(total_cost),
                    'material_cost': float(material_cost),
                    'labor_cost': float(labor_cost),
                    'overhead_cost': float(overhead_cost),
                    'other_cost': float(other_cost)
                },
                'details': details
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '成本分析失败'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['post'])
    def change_status(self, request, pk=None):
        """更改BOM状态"""
        try:
            bom = self.get_object()
            status_value = request.data.get('lifecycle_status')
            
            if not status_value:
                return Response({
                    'message': '状态值不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 验证状态值是否有效
            valid_statuses = [choice[0] for choice in BillOfMaterials.LIFECYCLE_STATUS_CHOICES_TUPLE]
            if status_value not in valid_statuses:
                return Response({
                    'message': '无效的状态值'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            bom.lifecycle_status = status_value
            bom.save()
            
            return Response({
                'bom_id': bom.bom_id,
                'new_status': bom.lifecycle_status,
                'message': '状态更改成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '状态更改失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def clone(self, request, pk=None):
        """克隆BOM并创建新版本"""
        try:
            original_bom = self.get_object()
            new_version = request.data.get('version')
            
            if not new_version:
                return Response({
                    'message': '新版本号不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查新版本号是否已存在
            if BillOfMaterials.objects.filter(product=original_bom.product, version=new_version).exists():
                return Response({
                    'message': '该产品的此版本BOM已存在'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 创建新BOM
            new_bom_data = {
                'product': original_bom.product,
                'bom_type': original_bom.bom_type,
                'version': new_version,
                'effective_date': original_bom.effective_date,
                'expiry_date': original_bom.expiry_date,
                'is_active': original_bom.is_active,
                'lifecycle_status': 'DESIGNING',  # 克隆后默认为设计中状态
                'description': original_bom.description,
                'creator': request.user,
                'configuration_template': original_bom.configuration_template,
                'routing_reference': original_bom.routing_reference
            }
            
            new_bom = BillOfMaterials.objects.create(**new_bom_data)
            
            # 克隆组件
            for component in original_bom.components.all():
                component_data = {
                    'bom': new_bom,
                    'material': component.material,
                    'quantity': component.quantity,
                    'unit': component.unit,
                    'usage_rate': component.usage_rate,
                    'scrap_rate': component.scrap_rate,
                    'sequence': component.sequence,
                    'unit_cost': component.unit_cost,
                    'total_cost': component.total_cost,
                    'operation_code': component.operation_code,
                    'operation_name': component.operation_name,
                    'workstation': component.workstation,
                    'lead_time': component.lead_time,
                    'preferred_supplier': component.preferred_supplier,
                    'supplier_part_number': component.supplier_part_number,
                    'procurement_type': component.procurement_type,
                    'quality_standard': component.quality_standard,
                    'certification_requirements': component.certification_requirements,
                    'attributes': component.attributes,
                    'description': component.description
                }
                
                new_component = BOMComponent.objects.create(**component_data)
                
                # 克隆替代物料
                for alt_material in component.alternative_material_set.all():
                    alt_data = {
                        'component': new_component,
                        'alternative_material': alt_material.alternative_material,
                        'substitution_ratio': alt_material.substitution_ratio,
                        'is_active': alt_material.is_active,
                        'approval_status': alt_material.approval_status,
                        'reason': alt_material.reason
                    }
                    AlternativeMaterial.objects.create(**alt_data)
            
            # 复制文档关联
            for doc in BOMDocument.objects.filter(bom=original_bom):
                doc_data = {
                    'document_type': doc.document_type,
                    'document_name': doc.document_name,
                    'file_path': doc.file_path,
                    'file_url': doc.file_url,
                    'version': doc.version,
                    'description': doc.description,
                    'bom': new_bom,
                    'creator': request.user
                }
                BOMDocument.objects.create(**doc_data)
            
            # 重新计算成本
            new_bom.cost = original_bom.cost
            new_bom.save()
            
            return Response({
                'new_bom_id': new_bom.bom_id,
                'version': new_bom.version,
                'message': 'BOM克隆成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': 'BOM克隆失败'
            }, status=status.HTTP_400_BAD_REQUEST)


class BOMComponentViewSet(CustomModelViewSet):
    """BOM组件视图集"""
    queryset = BOMComponent.objects.filter(is_deleted=False).order_by('sequence')
    serializer_class = BOMComponentSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['bom_id', 'material_id', 'parent_component_id']
    search_fields = ['material__name', 'material__sku', 'description']
    
    def get_queryset(self):
        """增强的查询集，支持软删除过滤和is_active状态过滤"""
        queryset = super().get_queryset()
        
        # 支持查看已删除的数据
        show_deleted = self.request.query_params.get('show_deleted', 'false')
        if show_deleted.lower() == 'true' and self.request.user.has_perm('product.view_deleted_component'):
            queryset = BOMComponent.objects.all().order_by('sequence')
        else:
            # 默认只显示激活状态的组件
            queryset = queryset.filter(is_active=True)
        
        return queryset
    
    def perform_destroy(self, instance):
        """实现软删除"""
        instance.is_deleted = True
        instance.save()
    
    @action(detail=True, methods=['post'])
    def restore(self, request, pk=None):
        """恢复已删除的组件"""
        try:
            instance = BOMComponent.objects.get(pk=pk)
            if instance.is_deleted:
                instance.is_deleted = False
                instance.save()
                return Response({'message': '组件恢复成功'})
            else:
                return Response({'message': '该组件未被删除'}, status=status.HTTP_400_BAD_REQUEST)
        except BOMComponent.DoesNotExist:
            return Response({'error': '组件不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    @action(detail=True, methods=['get'])
    def tree_view(self, request, pk=None):
        """获取组件的树形结构视图"""
        try:
            component = self.get_object()
            serializer = BOMComponentSerializer(component)
            return Response(serializer.data)
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '获取树形结构失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['get'])
    def alternatives(self, request, pk=None):
        """获取组件的替代物料列表"""
        try:
            component = self.get_object()
            alternatives = component.alternative_material_set.filter(is_active=True).all()
            serializer = AlternativeMaterialSerializer(alternatives, many=True)
            return Response(serializer.data)
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '获取替代物料失败'
            }, status=status.HTTP_400_BAD_REQUEST)
            
    @action(detail=True, methods=['post'])
    def change_component_status(self, request, pk=None):
        """更改组件状态（软删除/恢复）"""
        try:
            component = self.get_object()
            is_active = request.data.get('is_active')
            
            if is_active is None:
                return Response({
                    'message': 'is_active参数不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            component.is_active = is_active
            component.save()
            
            return Response({
                'component_id': component.component_id,
                'is_active': component.is_active,
                'message': '组件状态更新成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '组件状态更新失败'
            }, status=status.HTTP_400_BAD_REQUEST)


class BOMDocumentViewSet(CustomModelViewSet):
    """BOM文档视图集"""
    queryset = BOMDocument.objects.filter(is_deleted=False).order_by('-create_time')
    serializer_class = BOMDocumentSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['bom_id', 'component_id', 'document_type']
    search_fields = ['document_name', 'description']
    parser_classes = [MultiPartParser, FormParser]
    
    def get_queryset(self):
        """增强的查询集，支持软删除过滤"""
        queryset = super().get_queryset()
        
        # 支持查看已删除的数据
        show_deleted = self.request.query_params.get('show_deleted', 'false')
        if show_deleted.lower() == 'true' and self.request.user.has_perm('product.view_deleted_document'):
            queryset = BOMDocument.objects.all().order_by('-create_time')
        
        return queryset
    
    def perform_destroy(self, instance):
        """实现软删除"""
        instance.is_deleted = True
        instance.save()
    
    @action(detail=True, methods=['post'])
    def restore(self, request, pk=None):
        """恢复已删除的文档"""
        try:
            instance = BOMDocument.objects.get(pk=pk)
            if instance.is_deleted:
                instance.is_deleted = False
                instance.save()
                return Response({'message': '文档恢复成功'})
            else:
                return Response({'message': '该文档未被删除'}, status=status.HTTP_400_BAD_REQUEST)
        except BOMDocument.DoesNotExist:
            return Response({'error': '文档不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    @action(detail=False, methods=['post'])
    def upload(self, request):
        """上传BOM相关文档"""
        # 这里可以实现文件上传的逻辑
        # 通常会涉及文件保存和路径记录
        return Response({
            'message': '文档上传接口已预留'
        }, status=status.HTTP_200_OK)

class BOMVersionViewSet(CustomModelViewSet):
    """BOM版本管理视图集"""
    queryset = BOMVersion.objects.filter(is_deleted=False, is_active=True).order_by('-create_time')
    serializer_class = BOMVersionSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['bom_id', 'status', 'is_current', 'is_active']
    search_fields = ['version_number', 'change_reason', 'change_content']
    
    def get_queryset(self):
        """增强的查询集，支持软删除过滤和is_active状态过滤"""
        queryset = BOMVersion.objects.filter(is_deleted=False)
        
        # 支持查看非激活状态的版本
        show_inactive = self.request.query_params.get('show_inactive', 'false')
        if show_inactive.lower() != 'true':
            # 默认只显示激活状态的版本
            queryset = queryset.filter(is_active=True)
        
        # 支持查看已删除的数据
        show_deleted = self.request.query_params.get('show_deleted', 'false')
        if show_deleted.lower() == 'true' and self.request.user.has_perm('product.view_deleted_version'):
            queryset = BOMVersion.objects.all()
        
        return queryset.order_by('-create_time')
    
    def perform_destroy(self, instance):
        """实现软删除"""
        # 如果是当前版本，不允许删除
        if instance.is_current:
            raise ValidationError("当前版本不能被删除")
        instance.is_deleted = True
        instance.save()
    
    @action(detail=True, methods=['post'])
    def restore(self, request, pk=None):
        """恢复已删除的版本记录"""
        try:
            instance = BOMVersion.objects.get(pk=pk)
            if instance.is_deleted:
                instance.is_deleted = False
                instance.save()
                return Response({'message': '版本记录恢复成功'})
            else:
                return Response({'message': '该版本记录未被删除'}, status=status.HTTP_400_BAD_REQUEST)
        except BOMVersion.DoesNotExist:
            return Response({'error': '版本记录不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    @action(detail=True, methods=['post'])
    def change_status(self, request, pk=None):
        """更改版本状态（软删除/恢复）"""
        try:
            version = self.get_object()
            is_active = request.data.get('is_active')
            
            if is_active is None:
                return Response({
                    'message': 'is_active参数不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 当前版本不能被停用
            if version.is_current and not is_active:
                return Response({
                    'message': '当前版本不能被停用'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            version.is_active = is_active
            version.save()
            
            return Response({
                'version_id': version.version_id,
                'is_active': version.is_active,
                'message': '版本状态更新成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本状态更新失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def make_current(self, request, pk=None):
        """将版本设为当前版本"""
        try:
            version = self.get_object()
            
            # 检查版本是否激活
            if not version.is_active:
                return Response({
                    'message': '只有激活状态的版本才能设为当前版本'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 将同一BOM的其他版本设为非当前版本
            BOMVersion.objects.filter(bom=version.bom, is_current=True).update(is_current=False)
            # 设置当前版本
            version.is_current = True
            version.status = 'ACTIVE'
            version.save()
            # 更新BOM的当前版本
            bom = version.bom
            bom.current_version = version.version_number
            bom.save()
            
            return Response({
                'version_id': version.version_id,
                'message': '版本已设为当前版本'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '设置当前版本失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def rollback(self, request, pk=None):
        """回滚到指定版本"""
        try:
            version = self.get_object()
            
            # 检查版本是否激活
            if not version.is_active:
                return Response({
                    'message': '只有激活状态的版本才能回滚'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 创建新版本作为回滚的副本
            bom = version.bom
            
            # 生成新版本号 (例如: 如果当前是1.2，新版本为1.3)
            # 这里简化处理，实际应该根据当前版本号生成合理的新版本号
            new_version_number = f"{float(bom.current_version) + 0.1:.1f}"
            
            # 将当前版本设为非当前版本
            BOMVersion.objects.filter(bom=bom, is_current=True).update(is_current=False)
            
            # 创建新版本记录
            new_version = BOMVersion.objects.create(
                bom=bom,
                version_number=new_version_number,
                change_reason=f"回滚到版本 {version.version_number}",
                change_content=version.change_content,
                created_by=request.user,
                is_current=True,
                status='ACTIVE',
                is_active=True
            )
            
            # 更新BOM的当前版本
            bom.current_version = new_version_number
            bom.save()
            
            return Response({
                'version_id': new_version.version_id,
                'version_number': new_version.version_number,
                'message': '版本回滚成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本回滚失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['post'])
    def compare(self, request):
        """比较两个版本的差异"""
        try:
            version1_id = request.data.get('version1_id')
            version2_id = request.data.get('version2_id')
            
            if not version1_id or not version2_id:
                return Response({
                    'message': '版本ID不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取两个版本
            version1 = BOMVersion.objects.get(pk=version1_id)
            version2 = BOMVersion.objects.get(pk=version2_id)
            
            # 确保两个版本属于同一个BOM
            if version1.bom != version2.bom:
                return Response({
                    'message': '只能比较同一BOM的两个版本'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 这里应该实现详细的版本比较逻辑
            # 包括组件的增删改查等
            
            # 返回基本的比较信息
            return Response({
                'versions': [
                    {
                        'version_id': version1.version_id,
                        'version_number': version1.version_number,
                        'created_at': version1.create_time
                    },
                    {
                        'version_id': version2.version_id,
                        'version_number': version2.version_number,
                        'created_at': version2.create_time
                    }
                ],
                'component_changes': [],  # 这里应该填充实际的组件变更信息
                'message': '版本比较成功'
            })
        except BOMVersion.DoesNotExist:
            return Response({
                'message': '版本不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本比较失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def approve(self, request, pk=None):
        """审批版本"""
        try:
            version = self.get_object()
            version.approval_status = 'APPROVED'
            version.approved_by = request.user
            version.approved_at = timezone.now()
            version.status = 'ACTIVE'
            version.save()
            
            return Response({
                'version_id': version.version_id,
                'message': '版本审批成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '版本审批失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def reject(self, request, pk=None):
        """拒绝版本"""
        try:
            version = self.get_object()
            reason = request.data.get('reason', '')
            version.approval_status = 'REJECTED'
            version.reject_reason = reason
            version.approved_by = request.user
            version.approved_at = timezone.now()
            version.save()
            
            return Response({
                'version_id': version.version_id,
                'message': '版本已拒绝'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '拒绝版本失败'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['get'])
    def dict_data(self, request):
        """获取BOM模块相关的字典数据"""
        try:
            dict_type = request.query_params.get('dict_type')
            
            if dict_type:
                # 返回指定类型的字典数据
                data = get_dict_data_by_type(dict_type)
                return Response({
                    'dict_type': dict_type,
                    'data': data
                })
            else:
                # 返回所有BOM相关的字典类型
                bom_dict_types = [
                    'bom_type',
                    'bom_status',
                    'lifecycle_status',
                    'bom_version_status',
                    'approval_status',
                    'alt_material_status',
                    'material_type',
                    'document_type',
                    'bom_change_type',
                    'bom_cost_type',
                    'bom_simulation_type',
                    'bom_report_type',
                    'bom_permission_type',
                    'bom_flow_type',
                    'bom_flow_status',
                    'bom_step_type',
                    'bom_step_status'
                ]
                
                # 获取所有字典类型的数据
                result = {}
                for type_name in bom_dict_types:
                    result[type_name] = get_dict_data_by_type(type_name)
                
                return Response({
                    'dict_types': bom_dict_types,
                    'data': result
                })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '获取字典数据失败'
            }, status=status.HTTP_400_BAD_REQUEST)


class AlternativeMaterialViewSet(CustomModelViewSet):
    """替代物料视图集，支持软删除和状态管理"""
    queryset = AlternativeMaterial.objects.filter(is_deleted=False, is_active=True).order_by('-create_time')
    serializer_class = AlternativeMaterialSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['component_id', 'alternative_material_id', 'is_active', 'approval_status']
    search_fields = ['alternative_material__name', 'alternative_material__sku', 'reason']
    
    def get_queryset(self):
        """增强的查询集，支持软删除过滤和is_active状态过滤"""
        queryset = AlternativeMaterial.objects.filter(is_deleted=False)
        
        # 支持查看非激活状态的替代物料
        show_inactive = self.request.query_params.get('show_inactive', 'false')
        if show_inactive.lower() != 'true':
            # 默认只显示激活状态的替代物料
            queryset = queryset.filter(is_active=True)
        
        # 支持查看已删除的数据
        show_deleted = self.request.query_params.get('show_deleted', 'false')
        if show_deleted.lower() == 'true' and self.request.user.has_perm('product.view_deleted_alternative'):
            queryset = AlternativeMaterial.objects.all()
        
        return queryset.order_by('-create_time')
    
    def perform_destroy(self, instance):
        """实现软删除"""
        instance.is_deleted = True
        instance.save()
    
    @action(detail=True, methods=['post'])
    def restore(self, request, pk=None):
        """恢复已删除的替代物料"""
        try:
            instance = AlternativeMaterial.objects.get(pk=pk)
            if instance.is_deleted:
                instance.is_deleted = False
                instance.save()
                return Response({'message': '替代物料恢复成功'})
            else:
                return Response({'message': '该替代物料未被删除'}, status=status.HTTP_400_BAD_REQUEST)
        except AlternativeMaterial.DoesNotExist:
            return Response({'error': '替代物料不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    @action(detail=True, methods=['post'])
    def change_status(self, request, pk=None):
        """更改替代物料状态（激活/停用）"""
        try:
            alternative = self.get_object()
            is_active = request.data.get('is_active')
            
            if is_active is None:
                return Response({
                    'message': 'is_active参数不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            alternative.is_active = is_active
            alternative.save()
            
            return Response({
                'alt_material_id': alternative.alt_material_id,
                'is_active': alternative.is_active,
                'message': '替代物料状态更新成功'
            })
        except Exception as e:
            return Response({
                'error': str(e),
                'message': '替代物料状态更新失败'
            }, status=status.HTTP_400_BAD_REQUEST)